import { parentPort, workerData } from "worker_threads";
import path from "path";
import { MixIndicatorsTolerance, DataHandler, StrategyBacktest } from "../../trader";
import { getDistanceScore } from "../../trader/util";
import { Statistics, sample } from "../../trader/Statistics";
import { appendFileSync } from "fs";
import { KLineDTO } from "../kline-history/KLineHistory.entity";

export interface Message {
  type: string;
  [x: string]: any;
}

let history: KLineDTO[] = [];
let symbol = ''
if (parentPort) {
  sample.setVectors(workerData.symbol, workerData.period, workerData.vectors);
  history = workerData.history;
  // 在主进程或主线程中
  parentPort.on("message", msg => {
    const result = fitnessFunction(msg, workerData.symbol);
    parentPort.postMessage(result);
  });
} else {
  // 在 fork 或 worker 中
  process.on("message", msg => {
    if (msg.type && msg.type === 'workerData') {
      sample.setVectors(msg.workerData.symbol, msg.workerData.period, msg.workerData.vectors);
      history = msg.workerData.history;
      symbol = msg.workerData.symbol;
      return;
    }
    const result = fitnessFunction(msg, symbol);
    // 将结果发送给主线程
    process.send(result);
  });
}

export function fitnessFunction(genes, symbol?: string) {
  try {
    const { profitRate, maxDrawdownRate, ...others } = train(history, {
      mixIndicatorsTolerance: Statistics.vectorsToJson(genes, symbol)
    });
    
    if (maxDrawdownRate > -0.2 && profitRate > 0.5) {
      const resultFilePath = path.resolve(__dirname, './result.json');
      appendFileSync(resultFilePath, JSON.stringify({
        result: { maxDrawdownRate, profitRate, ...others },
        params: Statistics.vectorsToJson(genes, symbol)
      }))
    }
    let score = 0;
    if (maxDrawdownRate === 0) {
      score = 0;
    } else {
      score = getDistanceScore(Math.abs(maxDrawdownRate * 100)) / 3;
    }
    if (profitRate > 0) {
      score += profitRate * 100 * 2;
    }
    console.log(`profitRate： ${profitRate}`,  `maxDrawdownRate: ${maxDrawdownRate} score:${score}`)
    // score += getScore(others.buyCount, 12)
    return score;
  } catch (error) {
    console.log(error);
    return 0;
  }
}


export function train(history: KLineDTO[], options?: {
  mixIndicatorsTolerance?: MixIndicatorsTolerance
  code?: string
}) {
  const symbol = history[0].symbol
  const dataHander = new DataHandler('mock');
  const strategyBacktest = new StrategyBacktest({symbol, ...options});
  strategyBacktest.init(symbol);
  dataHander.on('interval:15m', (data) => {
    strategyBacktest.addData(data, '15m')
  });

  dataHander.on('interval:4h', (data) => {
    strategyBacktest.addData(data, '4h')
  });

  dataHander.on('interval:1d', (data) => {
    strategyBacktest.addData(data, '1d')
  });

  dataHander.on('update:4h', (data) => {
    strategyBacktest.updateData(data, '4h');
  });
  dataHander.on('update:1d', (data) => {
    strategyBacktest.updateData(data, '1d');
  });

  for (let i = 0; i < history.length; i++) {
    const element = history[i];
    dataHander.handleHistory({
      timestamp: new Date(element.time).getTime(),
      ...element,
    })
  }
  const result = strategyBacktest.getResult(symbol);
  // console.log(result)
  strategyBacktest.destroyed();
  return result
}
